#include "apue.h"
#include <errno.h>
#include <stdarg.h>
#include <syslog.h>

static void err_doit(int,int,const char*,va_list);

void err_ret(const char * fmt,...){
  va_list ap;
  va_start(ap,fmt);
  err_doit(1,errno,fmt,ap);
  va_end(ap);
}

void err_sys(const char*fmt,...){
  va_list ap;
  va_start(ap,fmt);
  err_doit(1,errno,fmt,ap);
  exit(1);
}

void err_cont(int error,const char *fmt,...){
  va_list ap;
  va_start(ap,fmt);
  err_doit(1,errno,fmt,ap);
  va_end(ap);
}

void err_exit(int error,const char* fmt,...){

  va_list ap;
  va_start(ap,fmt);
  err_doit(1,error,fmt,ap);
  va_end(ap);
}

void err_dump(const char* fmt,...){
  va_list ap;
  va_start(ap,fmt);
  err_doit(1,errno,fmt,ap);
  va_end(ap);
  abort();
  exit(1);
}

void err_msg(const char *fmt,...){
  va_list ap;
  va_start(ap,fmt);
  err_doit(0,0,fmt,ap);
  va_end(ap);
}

void err_quit(const char*fmt,...){
  va_list ap;
  va_start(ap,fmt);
  err_doit(0,0,fmt,ap);
  va_end(ap);
  exit(1);
}

static void err_doit(int errnoflag,int error,const char *fmt,va_list ap){
 char buf[MAXLINE] ;
 vsnprintf(buf,MAXLINE -1,fmt,ap);
 if(errnoflag){
  snprintf(buf+strlen(buf),MAXLINE-strlen(buf)-1,": %s",strerror(error));
 }
 strcat(buf,"\n");
 fflush(stdout);
 fputs(buf,stderr);
 fflush(NULL);
}

static void log_doit(int,int,int,const char*,va_list ap);

extern int log_to_stderr;

void log_open(const char *ident,int option,int facility){
  if(log_to_stderr == 0){
    openlog(ident,option,facility);
  }
}

void log_ret(const char *fmt,...){
  va_list ap;
  va_start(ap,fmt);
  log_doit(1,errno,LOG_ERR,fmt,ap);
  va_end(ap);
}

void log_sys(const char* fmt,...){
  va_list ap;
  va_start(ap,fmt);
  log_doit(1,errno,LOG_ERR,fmt,ap);
  va_end(ap);
}

void log_msg(const char*fmt,...){
  va_list ap;
  va_start(ap,fmt);
  log_doit(0,0,LOG_ERR,fmt,ap);
  va_end(ap);
}

void log_quit(const char* fmt,...){
  va_list ap;
  va_start(ap,fmt);
  log_doit(0,0,LOG_ERR,fmt,ap);
  va_end(ap);
  exit(2);
}

void log_exit(int error,const char* fmt,...){
  va_list ap;
  va_start(ap,fmt);
  log_doit(1,error,LOG_ERR,fmt,ap);
  va_end(ap);
  exit(2);
}

static void log_doit(int errnoflag,int error,int priority, const char* fmt,va_list ap)
{
  char buf[MAXLINE];
  vsnprintf(buf,MAXLINE-1,fmt,ap);
  if(errnoflag)
    snprintf(buf+strlen(buf),MAXLINE-strlen(buf)-1," : %s",strerror(error));
  strcat(buf,"\n");
  if(log_to_stderr){
    fflush(stdout);
    fputs(buf,stderr);
    fflush(stderr);
  }else{
    syslog(priority,"%s",buf);
  }
}
